/*
 * Copyright (c) 2003-2010, Live Media Pty. Ltd.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice, this list of
 *     conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice, this list of
 *     conditions and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *  3. Neither the name of Live Media nor the names of its contributors may be used to endorse
 *     or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.colony.remote.rpc;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.colony.remote.RemoteException;

public class RpcMetaSkeleton
implements RpcDelegate
{
	/**
	 * A helper class used to proces a request and invoke a proxy
	 * object.
	 * 
	 * @param request
	 * @throws SomException
	 */
	public void processRequest( RpcMetaMethodRequest request, Object target )
	throws RemoteException
	{
		// Setup the objects used to invoke the request.
		Object[] args = request.getArguments();
				
		Method method = request.getMetaMethod().getMethod();		

		if ( method == null )
			throw new RemoteException( "NativeMethod not found" );
			
		invoke( request, target, method, args );
	}
	
	/**
	 * This is a helper function used to invoke a function and catch
	 * any exceptions.
	 * 
	 * @param request
	 * @param method
	 * @param args
	 * @throws SomException
	 */
	private void invoke( RpcMetaMethodRequest request, Object object, Method method, Object[] args )
	throws RemoteException
	{
		Object ret = null;
		try
		{
			// Invoke the request.
			ret = method.invoke( object, args );
		}
		catch (IllegalAccessException e )
		{
			request.setException( e );
		}
		catch (InvocationTargetException e )
		{
			request.setException( e.getTargetException() );
			//e.getTargetException().printStackTrace();
			return;
		}

		// If we got a return value.  Push it onto the stack.
		if ( method.getReturnType() != void.class )
		{		
			//TypeMap map = request.getTypeMap();
			// 6/12/2003 - This is a problem.  If the return type is
			// polymorphic then the object will be serialised as the
			// base class, not the full polymorphic type.
			//int id = map.getId( method.getReturnType() );
			//int id = map.getId( ret.getClass() );
			if ( !method.getReturnType().isAssignableFrom( ret.getClass() ))
			{
				//System.out.println( "NvmSkeleton. possibly bad return value");
				//System.out.println( "Method return type: " + method.getReturnType().getName() );
				//System.out.println( "Actual Return: " + ret.getClass().getName() );
			}
			//request.push( id, ret );
			request.setReturnValue( ret );
		}			
	}

}
